﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Sendz.Model;
using Sendz.WebUI.Models;
using System.Text.RegularExpressions;
using Sendz.WebUI.Infrastructure;
using Ninject;

namespace Sendz.WebUI.Binders
{
    public class FormFieldModelBinder : CustomModelBinder
    {
        public override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            List<FormFieldViewModel> formresponses = new List<FormFieldViewModel>();
            var form = controllerContext.HttpContext.Request.Form;

            foreach (var key in form.AllKeys)
            {
                // All that should be required is the FormFieldKey and its updated Value
                if (key.IndexOf(".FormFieldKey") > -1)
                {
                    var thisGuid = Guid.Empty;
                    if (Guid.TryParse(form[key], out thisGuid))
                    {
                        var formresponse = new FormFieldViewModel();
                        // Todo: [MOB HELP!] make this IoC instead of literal EF call--ModelBinders are a pain for this and needing parameterless constructors
                        // Also, other IoC patterns seem to fail here (ref: http://ninject.codeplex.com/wikipage?title=Injection%20Patterns)
                        var dbForm = new EntityFormRepository();
                        var thisField = dbForm.GetFieldByKey(thisGuid);
                        var thisFieldType = dbForm.GetFieldTypeByKey(thisField.FieldTypeKey);
                        formresponse.FormFieldKey = thisGuid;
                        formresponse.Name = thisField.Name;
                        formresponse.ListEnum = thisField.ListEnum;
                        var valKey = key.Replace(".FormFieldKey", ".Value");
                        if (form[valKey] != null)
                        {
                            var thisValue = form[valKey];
                            var thisValueArr = new string[] { };
                            thisValueArr = form[valKey].Split(',');
                            // Commas are manually escaped on the form's view so the request isn't overly split-up, now convert them back
                            for (var i = 0; i < thisValueArr.Count(); i++)
                                thisValueArr[i] = thisValueArr[i].Replace("%comma%", ",");
                            formresponse.Value = thisValueArr;
                        }
                        // Perform custom validation at the model binder level since the view model has conditional logic
                        if (thisField.IsRequired && formresponse.Value == null)
                            bindingContext.ModelState.AddModelError(string.Format("formfields[{0}].Value", thisField.FormFieldKey), thisFieldType.RequiredErrorTemplate.Replace("%Name%", thisField.Name));
                        else if (thisField.IsRequired && string.IsNullOrEmpty(string.Join(string.Empty, formresponse.Value)))
                            bindingContext.ModelState.AddModelError(string.Format("formfields[{0}].Value", thisField.FormFieldKey), thisFieldType.RequiredErrorTemplate.Replace("%Name%", thisField.Name));
                        if (!string.IsNullOrEmpty(thisFieldType.RegEx))
                        {
                            var rxMatch = new Regex(thisFieldType.RegEx);
                            var thisVal = string.Empty;
                            if (formresponse.Value != null)
                                thisVal = string.Join(string.Empty, formresponse.Value);
                            if (!rxMatch.IsMatch(thisVal))
                                bindingContext.ModelState.AddModelError(string.Format("formfields[{0}].Value", thisField.FormFieldKey), thisFieldType.RegExError);
                        }
                        // Use a common helper to fill the options since the controller uses this too
                        var formDataHelpers = new Sendz.WebUI.Helpers.FormDataHelpers();
                        formresponse.Options = formDataHelpers.GetFieldOptions(thisField, formresponse);
                        formresponses.Add(formresponse);
                    }
                }
            }
            return formresponses;
        }

        private string ConvertEmptyStringToNull(string value)
        {
            return (string.IsNullOrEmpty(value) ? null : value);
        }
    }
}